<?php

class Application_View_Helper_LayoutLoader extends Zend_View_Helper_Abstract {
	
	const CONTAINER_ID_PREFIX = 'container_';
	const CONTAINER_CLASS 	  = 'widget_container';
	const WIDGET_CLASS 		  = 'widget';
	/**
	 * Use 960 grid framework for layout with total of 12 columns
	 */
	const TOTAL_COLUMNS = 12;
	
	private static $_posToClass = array(
		'first' => 'alpha',
		'last'  => 'omega',
	);
	
	/**
	 * Widget resources
	 * @var array
	 */
	private $_resources = array(
		'javascript' => array(), 
		'css' 		 => array(),
	);
	
	public function layoutLoader($cache = false) {
		/**
		 * Получаем текущий роутер
		 */
		$router    = Zend_Controller_Front::getInstance()->getRouter();
		$route     = $router->getCurrentRoute();
		
		$defaults   = ($route instanceof Zend_Controller_Router_Route_Chain) 
						? $route->match(Zend_Controller_Front::getInstance()->getRequest()) 
						: $route->getDefaults();
		//имя роутера
		$routeName = $defaults['module'] . '_' . $defaults['controller'] . '_' . $defaults['action'];
		$routeName = strtolower($routeName);
		/**
		 * Get the parameters from request
		 * and maybe we have to use them inside widgets later
		 */
		$requestParams = array();
		if ($route instanceof Zend_Controller_Router_Route_Regex) {
			$map = $route->getVariables();
			foreach ($map as $name) {
				/**
				 * I wish I can get the mapped values 
				 * ($_values property from Zend_Controller_Router_Route_Regex instance)
				 * Currently, I get the parameter's value from request 
				 */
				$value = Zend_Controller_Front::getInstance()->getRequest()->getParam($name);
				$requestParams[$name] = $value;
				//$this->view->assign($name, $value);
			}
		}
		//файл макета
		$file = Zend_Layout::getMvcInstance()->getLayoutPath() . DS . $routeName . '.xml';
		
		if (!file_exists($file)) {
			/**
			 * Если такого макета нет, то выводим контент как есть
			 */
			return $this->view->layout()->content;
		}
		
		$module 	= null;
		$widgetName = null;
		$load 		= null;
		
		$containerId 	   = 0;
		$widgetContainerId = 0;
		$tabId 			   = 0; 
		$tabContainerId    = 0;
		
		$params    = array();
		$params2   = array();
		$paramName = null;
		$from 	   = null;
		$search    = array('{APP_URL}', '{APP_STATIC_SERVER}');
		$replace   = array($this->view->baseUrl(), '');
		//сборка html шаблона из xml макета
		ob_start();
		//TODO: включить кеширование
		
		//открываем наш макет
		$reader = new XMLReader();
		$reader->open($file, 'UTF-8');
		//парсим
		while ($reader->read()) {
			$str = $reader->nodeType . '_' . $reader->localName;
			//начальный тег
			switch ($str) {
				case XMLReader::ELEMENT . '_description':
					break;
				case XMLReader::ELEMENT . '_layout':
					break;
				case XMLReader::ELEMENT . '_container':
					$containerId++;
					$widgetContainerId = 0;
					$cols = $reader->getAttribute('cols');
					if ($cols == null) {
						$class = '';
					} else {
						$class = (($position = $reader->getAttribute('position')) != null) 
									? 'grid_' . $cols . ' ' . self::$_posToClass[$position]
									: 'grid_' . $cols;
					}
								
					if ($cols == self::TOTAL_COLUMNS) {
						$class .= ' t_space_bottom';
					}
					$cssClass = $reader->getAttribute('cssClass');
					if (isset($cssClass)) {
						$class .= ' ' . $cssClass;
					}
					$str = '<div class="' . self::CONTAINER_CLASS . ' ' . $class . '" id="' . self::CONTAINER_ID_PREFIX . $containerId . '">'; 
					echo $str;
					
					
					break;
				case XMLReader::ELEMENT . '_defaultOutput':
					/**
					 * Обычный вывод контента
					 */
					echo $this->view->layout()->content;
					
					//TODO: запись в кеш
					
					break;
				//виджеты
				case XMLReader::ELEMENT . '_widget':
					$module     = $reader->getAttribute('module');
					$widgetName = $reader->getAttribute('name');
					$load       = $reader->getAttribute('load');
					if (!isset($load)) {
						$load = 'php';
					}
					
					$cssClass = $reader->getAttribute('cssClass');
					$cssClass = (!isset($cssClass)) ? '' : ' ' . $cssClass;
					
					$widgetContainerId++;
					$divId = self::CONTAINER_ID_PREFIX . $containerId . '_' . $widgetContainerId;
					$params['container']  = $divId;
					$params2['container'] = '"' . $divId . '"';
					$str = '<div class="' . self::WIDGET_CLASS . $cssClass . '" id="' . $divId . '">';
					echo $str;
					
					//TODO: запись в кеш
					break;
				case XMLReader::ELEMENT . '_params':
					break;
				case XMLReader::ELEMENT . '_param':
					$paramName = $reader->getAttribute('name');
					$from      = ($reader->getAttribute('from') == null) 
									? $paramName : $reader->getAttribute('from');
					if ($reader->getAttribute('type') == 'global' && isset($requestParams[$from])) {
						$params[$paramName]  = $requestParams[$from];
						$params2[$paramName] = '$this->view->' . $from;
					}
					
					break;
				case XMLReader::CDATA:
					$paramValue = ($reader->value == null) 
								? $reader->readString() : $reader->value;
					if ($reader->getAttribute('type') != 'global' || !isset($requestParams[$from])) {
						$params[$paramName]  = $paramValue;
						$params2[$paramName] = '"' . addslashes($paramValue) . '"';
					}
					break;
				case XMLReader::ELEMENT . '_resources':
					break;
				//ресурсы аля js и css
				case XMLReader::ELEMENT . '_resource':
					$resourceType = $reader->getAttribute('type');
					$src          = $reader->getAttribute('src');
					
					if (in_array($resourceType, array('javascript', 'css'))) {
						if (!in_array($src, $this->_resources[$resourceType])) {
							$this->_resources[$resourceType][] = $src;				
						}
						
						/**
						 * TODO: Load CSS at the head section by javascript
						 */
						if ($resourceType == 'css') {
							echo '<link rel="stylesheet" type="text/css" href="' . str_replace($search, $replace, $src) . '" />';
							//echo $this->view->headLink()->appendStylesheet(str_replace($search, $replace, $src));
						}
					} else {
						throw new Exception('Does not support ' . $resourceType . ' for type of resource');
					}
					break;
				
				//конечные теги
				case XMLReader::END_ELEMENT . '_description':
					break;
				case XMLReader::END_ELEMENT . '_layout':
					break;
				case XMLReader::END_ELEMENT . '_container':
					echo '</div>';
					
					break;
				case XMLReader::END_ELEMENT . '_widget':
					if ($module != null) {
						if ('php' == $load) {
							echo $this->view->widget($module, $widgetName, $params);
							
							//TODO: кешировать
						} elseif ('ajax' == $load) {
							//TODO: сделать ajax загрузку виджетов
						}
					}
					
					$module 	  = null;
					$widgetName   = null;
					$load 		  = null;
					$paramName 	  = null;
					$from 		  = null;
					$params 	  = array();
					$params2 	  = array();
					
					echo '</div>';
					
					//TODO: запись в кеш
					break;
				case XMLReader::END_ELEMENT . '_params':
					break;
					
				case XMLReader::END_ELEMENT . '_param':
					break;
			}
		}
		
		$reader->close();
		
		
		$return = ob_get_clean();
		//подключаем js из ресурсов
		
		foreach ($this->_resources['javascript'] as $resource) {
			$resource = str_replace($search, $replace, $resource);
			$this->view->headScript()->appendFile($resource);
			
			//TODO: кешировать
		}
		return $return;
	}
}